package com.hengpeng.msls.port.impl;

import java.nio.charset.Charset;
import java.util.ArrayList;
import java.util.List;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.springframework.beans.BeansException;
import org.springframework.context.ApplicationContext;
import org.springframework.context.ApplicationContextAware;
import org.springframework.context.annotation.Lazy;
import org.springframework.http.HttpEntity;
import org.springframework.http.HttpHeaders;
import org.springframework.http.MediaType;
import org.springframework.stereotype.Component;
import org.springframework.web.client.RestTemplate;

import com.google.gson.Gson;
import com.hengpeng.common.configuration.ConfigProvider;
import com.hengpeng.common.configuration.ConfigProviderFactory;
import com.hengpeng.common.constant.Constant;
import com.hengpeng.common.persist.QueryParameter;
import com.hengpeng.common.persist.QueryResult;
import com.hengpeng.common.persist.entity.AbstractEntity;
import com.hengpeng.common.persist.query.DynamicQuery;
import com.hengpeng.common.persist.query.Restrictions;
import com.hengpeng.itfinbase.message.ResponseMessage;
import com.hengpeng.itfinbase.message.TransMessage;
import com.hengpeng.msls.port.PortFactory;

@Component("portFactoryImpl")
@Lazy
public class PortFactoryImpl implements PortFactory, ApplicationContextAware
{
	public final static Log logger = LogFactory.getLog(PortFactoryImpl.class);

	private final static ConfigProvider<String> cp = ConfigProviderFactory
			.getInstance(Constant.HP_COMMON_PROPERTIES_FILEPATH);

	private static HttpHeaders httpHeaders = null;

	private RestTemplate restTemplate = null;

	String DigestAuth_ClientId = "clientbasic";

	String DigestAuth_ClientPwd = "clientbasic4happycp";

	String DigestAuth_Key = "acegi";

	String DigestAuth_RealName = "Contacts Realm via Digest Authentication";

	public static HttpHeaders createBasicAuthHeaders(String userName, String password)
	{
		if (httpHeaders == null)
		{
			httpHeaders = new HttpHeaders();
			// Authorization
			String userPassword = userName + ":" + password;
			String encoding = new String(org.apache.commons.codec.binary.Base64.encodeBase64(userPassword.getBytes()),
					Charset.forName("UTF-8"));
			httpHeaders.set("Authorization", "Basic " + encoding);
			// Accept
			List<MediaType> mediaTypes = new ArrayList<MediaType>();
			httpHeaders.setContentType(MediaType.APPLICATION_XML);
			mediaTypes.add(MediaType.APPLICATION_XML);
			// mediaTypes.add(MediaType.APPLICATION_JSON);
			httpHeaders.setAccept(mediaTypes);
			httpHeaders.set("Accept-Charset", "UTF-8");
		}
		return httpHeaders;
	}

	public <T> T doPostTrans(String transName, Class<T> returnType, Object parameter, Object... pathValue)
	{
		String url = cp.getConfigByPrimaryKey("PortServiceUrl") + "/RemoteService/" + transName;
		HttpEntity<Object> entity = new HttpEntity<Object>(parameter, createBasicAuthHeaders(DigestAuth_ClientId,
				DigestAuth_ClientPwd));
		return (T) restTemplate.postForEntity(url, entity, returnType, pathValue).getBody();
	}

	public <T extends AbstractEntity> Long count(Class<T> type, DynamicQuery query)
	{
		QueryParameter<T> queryParameters = new QueryParameter<T>();
		queryParameters.setType(type);
		queryParameters.setCustomQuery(query);
		QueryResult<?> doPostTrans = this.remoteQuery(queryParameters);
		return (Long) doPostTrans.getResults().get(0);
	}

	@SuppressWarnings("unchecked")
	public <T extends AbstractEntity> List<Object> findObject(Class<T> type, DynamicQuery query)
	{
		QueryParameter<T> queryParameters = new QueryParameter<T>();
		queryParameters.setType(type);
		queryParameters.setCustomQuery(query);
		QueryResult<?> doPostTrans = this.remoteQuery(queryParameters);
		return (List<Object>) doPostTrans.getResults();
	}

	public <T extends AbstractEntity> T getEntity(DynamicQuery query, Class<T> clz)
	{
		List<T> list = queryList(query, clz);
		return list != null && list.size() > 0 ? list.get(0) : null;
	}

	public <T extends AbstractEntity> T getEntityById(Object id, Class<T> clz)
	{
		if (id == null)
		{
			return null;
		}
		DynamicQuery query = new DynamicQuery(clz);
		query.add(Restrictions.eq("id", id));
		return getEntity(query, clz);
	}

	@SuppressWarnings("rawtypes")
	public Integer getSingleInteger(DynamicQuery query)
	{
		List list = queryList(query, null);
		if (list.size() > 0)
		{
			if (list.get(0) != null)
			{
				return Integer.parseInt(list.get(0).toString());
			}
			else
			{
				return null;
			}
		}
		return null;
	}

	public <T extends AbstractEntity> List<T> queryList(DynamicQuery query, Class<T> clz)
	{
		QueryParameter<T> qp = new QueryParameter<T>();
		qp.setCustomQuery(query);
		qp.setType(clz);
		List<T> result = remoteQuery(qp).getResults();
		return result == null ? new ArrayList<T>() : result;
	}

	@Override
	public <T extends AbstractEntity> QueryResult<T> remoteQuery(DynamicQuery query, Class<T> clz)
	{
		QueryParameter<T> qp = new QueryParameter<T>();
		qp.setCustomQuery(query);
		qp.setType(clz);
		return this.remoteQuery(qp);
	}

	@SuppressWarnings("unchecked")
	@Override
	public <T extends AbstractEntity> QueryResult<T> remoteQuery(QueryParameter<T> queryParameters)
	{
		QueryResult<T> doPostTrans = this.doPostTrans("remoteQuery", QueryResult.class, queryParameters);
		if (!doPostTrans.getIsSuccess())
		{
			logger.error("远程查询请求处理错误, Query{" + queryParameters.getCustomQuery().getSqlResult().getSql()
					+ "}, Parameter{" + queryParameters.getCustomQuery().getSqlResult().getParamsList() + "}");
		}
		return doPostTrans;
	}

	@Override
	public ResponseMessage remoteTrans(TransMessage transMessage)
	{
		Gson gson = new Gson();
		logger.info("远程交易请求,【transType=" + transMessage.getTransType() + "】,请求参数:{" + gson.toJson(transMessage) + "}");
		ResponseMessage doPostTrans = this.doPostTrans("remoteTrans", ResponseMessage.class, transMessage);
		logger.info("远程交易请求,【transType=" + transMessage.getTransType() + "】,响应信息:{" + gson.toJson(doPostTrans) + "}");
		return doPostTrans;
	}

	public <T extends ResponseMessage> T remoteTrans(TransMessage transMessage, Class<T> clz)
	{
		return clz.cast(remoteTrans(transMessage));
	}

	@Override
	public void setApplicationContext(ApplicationContext context) throws BeansException
	{
		restTemplate = context.getBean(RestTemplate.class);
		DigestAuth_ClientId = cp.getConfigByPrimaryKey("DigestAuth_ClientId");
		DigestAuth_ClientPwd = cp.getConfigByPrimaryKey("DigestAuth_ClientPwd");
		DigestAuth_Key = cp.getConfigByPrimaryKey("DigestAuth_Key");
		DigestAuth_RealName = cp.getConfigByPrimaryKey("DigestAuth_RealName");
	}

	@SuppressWarnings("all")
	public List<Object> queryList(DynamicQuery query)
	{
		QueryParameter qp = new QueryParameter();
		qp.setCustomQuery(query);
		List<Object> result = remoteQuery(qp).getResults();
		return result == null ? new ArrayList<Object>() : result;
	}
}
